# -*- coding:utf-8 -*-
# utils/utils_func.py

import asyncio
import math
from datetime import datetime
from sanic.log import logger


def datetime_to_str(dt, fmt="%Y-%m-%d %H:%M:%S"):
    """
    转化时间字符串
    """
    dt_str = ""
    if dt:
        dt_str = datetime.strftime(dt, fmt)
    return dt_str


# Retry decorator with exponential backoff
def retry(tries, delay=3, backoff=2):
    '''Retries a function or method until it returns True.

    delay sets the initial delay in seconds, and backoff sets the factor by which
    the delay should lengthen after each failure. backoff must be greater than 1,
    or else it isn't really a backoff. tries must be at least 0, and delay
    greater than 0.'''

    if backoff <= 1:
        raise ValueError("backoff must be greater than 1")

    tries = math.floor(tries)
    if tries < 0:
        raise ValueError("tries must be 0 or greater")

    if delay <= 0:
        raise ValueError("delay must be greater than 0")

    def deco_retry(f):
        async def f_retry(*args, **kwargs):
            mtries, mdelay = tries, delay  # make mutable
            for i in range(mtries):
                try:
                    logger.warn("try times:%s" % i)
                    await f(*args, **kwargs)  # first attempt
                    return True
                except Exception as e:
                    logger.error(e)
                    await asyncio.sleep(mdelay)  # wait...
                    mdelay *= backoff  # make future wait longer

            return False  # Ran out of tries :-(

        return f_retry  # true decorator -> decorated function

    return deco_retry  # @retry(arg[, ...]) -> true decorator
